package com.kizuki.thread;

import org.junit.Test;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class ProducerConsumer02 {

    @Test
    public void TestLockPC(){
        Data2 data = new Data2();

        new Thread(()->{
            for (int i  = 0; i < 20; i ++) {
                data.add();
            }
        }, "生产者").start();

        new Thread(()->{
            for (int i  = 0; i < 20; i ++) {
                data.dec();
            }
        }, "消费者").start();

    }
}

// 判断条件->业务->通知
class Data2 {
    private int number = 0;
    private Lock lock = new ReentrantLock();
    private Condition c0 = lock.newCondition(); // 用来精准的通知
    private Condition c1 = lock.newCondition();

    public void add() {
        lock.lock(); // lock
        try { // 业务
            while (number != 0) {
                c0.await();
            }
            System.out.println(Thread.currentThread().getName() + "生产了data 此时number = " + (++number));
            c1.signal(); // 精准唤醒c1
//            c1.signalAll(); // 唤醒全部
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock(); // unlock
        }
    }

    public void dec() {
        lock.lock();
        try {
            while (number == 0) {
                c1.await();
            }
            System.out.println(Thread.currentThread().getName() + "消费了data 此时number = " + (--number));
            c0.signal();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

}
